---
title: 迪米特法则
description: Law of Demeter (LoD) - 最少知识原则
sidebar_position: 4
---

# 迪米特法则

## 什么是迪米特法则

迪米特法则（Law of Demeter，简称 LoD）也称为最少知识原则（The Least Knowledge Principle），其核心思想是：

> 每个模块只应该了解那些与它关系密切的模块的有限知识。或者说，每个模块只和自己的朋友"说话"，不和陌生人"说话"。

具体来说，迪米特法则包含两个核心要点：
1. 不该有直接依赖关系的类之间，不要有依赖
2. 有依赖关系的类之间，尽量只依赖必要的接口

## 如何实现"高内聚、松耦合"

迪米特法则的主要目标是实现代码的"高内聚、松耦合"：

### 高内聚
- 相近的功能应该放到同一个类中
- 不相近的功能不要放到同一个类中
- 功能修改时，修改点比较集中，容易维护

### 松耦合
- 类与类之间的依赖关系简单清晰
- 一个类的修改对其他类的影响较小
- 修改时只需要考虑有限的依赖关系

## 代码示例

### 1. 违反迪米特法则的示例

```java
// 网络传输类不应该直接依赖特定的请求类型
public class NetworkTransporter {
    public byte[] send(HtmlRequest htmlRequest) {
        String address = htmlRequest.getAddress();
        byte[] data = htmlRequest.getContent().getBytes();
        // 发送数据...
        return null;
    }
}

public class HtmlDownloader {
    private NetworkTransporter transporter;
    
    public Html downloadHtml(String url) {
        HtmlRequest request = new HtmlRequest(url);
        byte[] rawHtml = transporter.send(request);
        return new Html(rawHtml);
    }
}
```

### 2. 符合迪米特法则的重构

```java
// 网络传输类只依赖通用的参数
public class NetworkTransporter {
    public byte[] send(String address, byte[] data) {
        // 发送数据...
        return null;
    }
}

public class HtmlDownloader {
    private NetworkTransporter transporter;
    
    public Html downloadHtml(String url) {
        HtmlRequest request = new HtmlRequest(url);
        byte[] rawHtml = transporter.send(
            request.getAddress(), 
            request.getContent().getBytes()
        );
        return new Html(rawHtml);
    }
}
```

### 3. 使用接口实现功能隔离

```java
// 定义序列化接口
public interface Serializable {
    String serialize(Object object);
}

// 定义反序列化接口
public interface Deserializable {
    Object deserialize(String text);
}

// 实现类同时实现两个接口
public class Serialization implements Serializable, Deserializable {
    @Override
    public String serialize(Object object) {
        // 序列化实现...
        return null;
    }
    
    @Override
    public Object deserialize(String text) {
        // 反序列化实现...
        return null;
    }
}

// 客户端代码只依赖需要的接口
public class Client1 {
    private Serializable serializer;
    
    public Client1(Serializable serializer) {
        this.serializer = serializer;
    }
}

public class Client2 {
    private Deserializable deserializer;
    
    public Client2(Deserializable deserializer) {
        this.deserializer = deserializer;
    }
}
```

## 实践建议

1. **合理划分类的职责**
   - 避免类之间不必要的依赖
   - 保持类的功能单一和内聚

2. **使用接口进行隔离**
   - 通过接口定义有限的访问边界
   - 客户端只依赖必要的接口

3. **注意依赖关系**
   - 减少类之间的直接依赖
   - 使用依赖注入等方式管理依赖

4. **平衡设计**
   - 不要过度设计，导致代码过于复杂
   - 在实际应用中灵活把握原则

## 与其他原则的关系

迪米特法则与其他设计原则的关系：

1. **单一职责原则**
   - 都强调高内聚
   - 通过职责划分降低耦合

2. **接口隔离原则**
   - 都强调最小化依赖
   - 通过接口定义依赖边界

3. **基于接口而非实现编程**
   - 都强调降低耦合
   - 通过抽象隔离具体实现

## 总结

迪米特法则的核心是实现"高内聚、松耦合"：

1. 通过合理划分类的职责，实现高内聚
2. 通过最小化依赖关系，实现松耦合
3. 通过接口隔离，控制依赖范围
4. 在实践中需要平衡，避免过度设计

